package ads1ss09.pa1;

import java.io.File;
import java.io.FileInputStream;

/**
 * Diese Klasse enth&auml;lt nur die {@link #main main()}-Methode zum Starten
 * des Programms.
 *
 * <p>
 * <b>WICHTIG:</b> Nehmen Sie keine &Auml;nderungen in dieser Klasse vor.
 * Bei der Abgabe werden diese &Auml;nderungen verworfen und es k&ouml;nnte
 * dadurch passieren, dass Ihr Programm somit nicht mehr korrekt
 * funktioniert.
 * </p>
 */
public final class Main
{

private static boolean test;
private static String fileName;
private static int size;
private static ThreadedBinaryTree tree;
private static InputScanner scanner;

// Constructor is private to hide it from JavaDoc.
private
Main()
{
} // Constructor

protected static void
bailOut( String msg )
{
	System.err.println((test ? chopedFileName() + ": " : "")
		+ "ERR " + msg);
	System.exit(1);
}

private static void
processInput( InputScanner.ValueType type, int value ) throws Exception
{
	switch (scanner.getType()) {
		case INVALID:
			throw new Exception("Invalid scanner access");
		case INSERT:
			// System.err.println("INSERT " + value);
			tree.insert(value);
			size++;

			break;
		case REMOVE:
			bailOut("input may not contain the #remove directive");
			// System.err.println("REMOVE " + value);
			/*
			tree.remove(value);
			size--;
			*/

			break;
		case FIND:
			// System.err.println("FIND " + value);
			tree.find(value);

			break;
		default:
			assert false
				: "This should be unreachable";
	}
}

private static String
chopedFileName()
{
	int i = fileName.lastIndexOf(File.separatorChar);

	if (i > 0) i = fileName.lastIndexOf(File.separatorChar, i - 1);
	if (i == -1) i = 0;

	return ((i > 0) ? "..." : "") + fileName.substring(i);
}

/**
 * Liest die Daten einer Testinstanz ein und &uuml;bergibt sie
 * an die entsprechenden Methoden der Baum-Implementierung.
 *
 * <p>
 * Die Option <code>-v</code> bewirkt, dass bei einer fehlerfreien
 * Durchf&uuml;hrung gleich nach dem <code>OK</code> auch die Zeit,
 * die das Programm gelaufen ist, in Millisekunden ausgegeben wird.
 * </p>
 *
 * <p>
 * Wenn die Option <code>-t</code> verwendet wird, wird jeder Ausgabe
 * der Dateiname der Inputinstanz vorangestellt. Im Falle einer
 * fehlerfreien Abarbeitung, wird nur <code>OK</code> gefolgt von der
 * Ausf&uuml;hrungszeit in Millisekunden ausgegeben.
 * </p>
 *
 * <p>
 * Der erste andere String in <code>args</code> wird als der Name der
 * Datei interpretiert, aus der die Testinstanz auszulesen ist. Wird
 * kein Dateiname angegeben, wird die Testinstanz &uuml;ber
 * {@link System#in} eingelesen.
 * </p>
 *
 * <p>
 * M&ouml;glicherweise auftretende Exceptions werden auf
 * {@link System#err} ausgegeben.
 * </p>
 * 
 * @param args Die von der Kommandozeile &uuml;bergebenen Argumente.
 * 	Mit der Option <code>-v</code> wird die ben&ouml;tigte Zeit
 * 	ausgegeben, w&auml;hrend <code>-t</code> den Dateinamen der
 * 	Inputinstanz voranstellt. Der erste andere String wird als Dateiname
 * 	interpretiert.
 */
public static void
main( String[] args )
{
	long start, end, offs;
	boolean stat = false;

	test = false;
	fileName = null;
	size = 0;
	scanner = null;
	tree = new ThreadedBinaryTree();

	for (String a: args) {
		if (a.equals("-v")) stat = true;
		else if (a.equals("-t")) test = true;
		else if (fileName == null) fileName = a;
		else System.err.println("WARN ignoring argument \""+a+"\"");
	}

	if (fileName != null) try {
		scanner = new InputScanner(new FileInputStream(fileName));
	} catch (Exception e) {
		System.err.println("WARN could not open "
			+ "file \"" + fileName + "\", reading "
			+ "from System.in");
	}

	if (scanner == null) {
		fileName = "System.in";
		scanner = new InputScanner(System.in);
	}

	start = System.currentTimeMillis();
	end = System.currentTimeMillis();
	offs = end - start;

	int v = -1;

	start = System.currentTimeMillis();
	try {

		while (scanner.nextValue()) {
			v = scanner.getValue();
			processInput(scanner.getType(), v);

			if (scanner.debugRequested()) {
				System.err.println("#debug "
					+ tree.preorder(size) + " "
					+ tree.postorder(size));
			}
		}
	} catch (Exception e) {
		e.printStackTrace();
		bailOut("Exception " + e.toString() + " ist waehrend dem "
			+ "Einfuegen von " + v + " aufgetreten");
	}
	end = System.currentTimeMillis();

	String testName = "Suchbaumeigenschaft";
	String pro = "";
	String poo = "";

	try {
		tree.testSearchTree();
		testName = "Threads, links nach rechts";
		tree.checkLtr();
		testName = "Threads, rechts nach links";
		tree.checkRtl();
		testName = "Preorder";
		pro = tree.preorder(size);
		testName = "Postorder";
		poo = tree.postorder(size);
	} catch (Exception e) {
		e.printStackTrace();
		bailOut("Exception " + e.toString() + " ist waehrend "
			+ " der ueberpruefung der Loesung aufgetreten ("
			+ testName + ")");
	}

	if (test) {
		System.out.println(chopedFileName()
			+ ": OK "
			+ (end - start - offs) + " ms");
	} else {
		System.out.println("OK"
			+ (stat ? " " + (end - start - offs) : "")
			+ " " + pro + " " + poo);
	}
} // void main()

} // class Main
